precision highp float;

uniform mat3 u_transform;
uniform mat3 u_split_transform;
uniform vec2 u_input_scale;
uniform vec2 u_input_size;

attribute vec2 attPosition;
attribute vec2 attUV;

varying vec2 v_scene_uv;
varying vec2 v_input_uv;
varying vec2 v_split_uv;


mat3 inverse3x3 (mat3 m) {
    vec3 c0 = m[0];
    vec3 c1 = m[1];
    vec3 c2 = m[2];
    vec3 b0 = c2.zxy * c1.yzx - c1.zxy * c2.yzx;
    vec3 b2 = c1.zxy * c0.yzx - c0.zxy * c1.yzx;
    vec3 b1 = c0.zxy * c2.yzx - c2.zxy * c0.yzx;
    return mat3(b0.x, b1.x, b2.x, b0.y, b1.y, b2.y, b0.z, b1.z, b2.z) / dot(c0, b0);
}

vec2 view2mask (mat3 mask2view_transform, vec2 mask_size, vec2 view_size, vec2 view_scale, vec2 view_uv) {
    vec2 view_xy = view_uv * view_size / view_scale;
    vec3 mask_xy = inverse3x3(mask2view_transform) * vec3(view_xy, 1.0); // No fucking inverse() ???
    return mask_xy.xy / mask_size;
}

vec2 mask2view (mat3 mask2view_transform, vec2 mask_size, vec2 view_size, vec2 view_scale, vec2 mask_uv) {
    vec2 mask_xy = mask_uv * mask_size;
    vec3 view_xy = mask2view_transform * vec3(mask_xy, 1.0);
    return view_xy.xy * view_scale / view_size;
}


void main () {
    vec3 position = u_transform * vec3(attPosition, 1.0);
    v_scene_uv = position.xy * 0.5 + 0.5;
    v_input_uv = attUV;
    v_split_uv = view2mask(u_split_transform, vec2(128.0), u_input_size, u_input_scale, attUV);
    gl_Position = vec4(position.xy, 0.0, 1.0);
}
